﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using System.Reflection;

namespace PublishingEditorServiceLibrary
{
    public class PublishingEditorService : IPublishingEditorService
    {
        private DataContext context = null;
        private const int ServiceID = 4;

        public PublishingEditorService()
        {
            context = new DataContext();
            Logger.type = "publish";
        }

        public Response GetArticlesFromPortfolio()
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                int sentToPortfolio = (int)MaturityStages.AddedToPortfolio;
                int removed = (int)MaturityStages.RemovedFromIssuePlan;
                var articles = (from a in context.Articles where a.status == sentToPortfolio || a.status == removed select a).ToList();
                if (articles.Count == 0)
                {
                    response.Error.Details = "Artiles in portfolio not found";
                    response.Error.TargetSite = MethodBase.GetCurrentMethod().Name;
                    response.Error.Type = ErrorTypes.ObjectNotFound;
                }
                else
                {
                    response.Result.AddRange(articles);
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response CreateIssuePlan(string title, DateTime publishDate)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var issuePlan = new Issue()
                {
                    Title = title,
                    PublishDate = publishDate,
                    IsPublished = false
                };

                lock (context)
                {
                    context.Issues.Add(issuePlan);
                    context.SaveChanges();
                }
                response.Result.Add(issuePlan);
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response AddNewSectionToIssuePlan(string title, string description, string issueID)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                lock (context)
                {
                    var issue = (from i in context.Issues where i.ID == issueID select i).SingleOrDefault();
                    if (issue != null)
                    {
                        var section = new Section()
                        {
                            ParentID = issue.ID,
                            Title = title,
                            Description = description
                        };

                        var issueSection = new IssueSection()
                        {
                            IssueID = issue.ID,
                            SectionID = section.ID
                        };
                        context.Sections.Add(section);
                        context.IssueSections.Add(issueSection);
                        context.SaveChanges();
                        response.Result.Add(section);
                    }
                    else
                    {
                        response.Error = new Error()
                        {
                            Details = "Issue plan with id " + issueID + " not found",
                            TargetSite = MethodBase.GetCurrentMethod().Name,
                            Type = ErrorTypes.ObjectNotFound
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response GetIssuePlans()
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var issues = (from i in context.Issues where !i.IsPublished select i).ToList();
                if (issues.Count == 0)
                {
                    response.Error = new Error()
                    {
                        Type = ErrorTypes.ObjectNotFound,
                        Details = "Published issues not found.",
                        TargetSite = MethodBase.GetCurrentMethod().Name
                    };
                }
                else
                {
                    response.Result.AddRange(issues);
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        private Issue GetIssuePlanContents(string issueID)
        {
            var issue = (from i in context.Issues where i.ID == issueID select i).SingleOrDefault();
            if (issue != null)
            {
                var sections = (from s in context.Sections 
                                from IS in context.IssueSections 
                                where IS.IssueID == issueID && s.ID == IS.SectionID 
                                select s).ToList();

                foreach (var s in sections)
                {
                    var articles = (from a in context.Articles 
                                    from SA in context.SectionArticles
                                    where SA.SectionID == s.ID && a.ID == SA.ArticleID 
                                    select a).ToList();

                    s.Articles.AddRange(articles);
                }
                issue.Sections.AddRange(sections);
                return issue;
            }
            else
            {
                return null;
            }
        }

        public Response GetIssuePlanDetails(string issueID)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var issue = GetIssuePlanContents(issueID);
                if (issue != null)
                {
                    response.Result.Add(issue);
                }
                else
                {
                    response.Error.Type = ErrorTypes.ObjectNotFound;
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response RemoveIssuePlan(string issueID)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var issue = (from i in context.Issues where i.ID == issueID select i).SingleOrDefault();
                if (issue != null)
                {
                    
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response RemoveSectionFromIssuePlan(string sectionID, string issueID)
        {
            throw new NotImplementedException();
        }

        public Response AddArticleToSection(string sectionID, string articleID)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var section = (from s in context.Sections where s.ID == sectionID select s).SingleOrDefault();
                if (section != null)
                {
                    var article = (from a in context.Articles where a.ID == articleID select a).SingleOrDefault();
                    if (article != null)
                    {
                        var sectionArticle = new SectionArticle()
                        {
                            ArticleID = articleID,
                            SectionID = sectionID
                        };
                        lock (context)
                        {
                            article.Stage = MaturityStages.AddedToIssuePlan;
                            context.SectionArticles.Add(sectionArticle);
                            context.SaveChanges();
                        }
                    }
                    else
                    {
                        response.Error = new Error()
                        {
                            Details = "Article with id " + articleID + " not found",
                            TargetSite = MethodBase.GetCurrentMethod().Name,
                            Type = ErrorTypes.ObjectNotFound
                        };
                    }
                }
                else
                {
                    response.Error = new Error()
                    {
                        Details = "Section with id " + sectionID + " not found",
                        TargetSite = MethodBase.GetCurrentMethod().Name,
                        Type = ErrorTypes.ObjectNotFound
                    };
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response RemoveArticleFromSection(string sectionID, string articleID)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                
                var sectionArticle = (from sa in context.SectionArticles 
                                      where sa.SectionID == sectionID && sa.ArticleID == articleID 
                                      select sa).SingleOrDefault();
                
                if (sectionArticle != null)
                {
                    var article = (from a in context.Articles where a.ID == articleID select a).SingleOrDefault();

                    if (article != null)
                    {
                        lock (context)
                        {
                            article.Stage = MaturityStages.RemovedFromIssuePlan;
                            context.SectionArticles.Remove(sectionArticle);
                            context.SaveChanges();
                        }
                    }
                    else
                    {
                        response.Error = new Error()
                        {
                            Details = "Article with id " + articleID + " not found",
                            TargetSite = MethodBase.GetCurrentMethod().Name,
                            Type = ErrorTypes.ObjectNotFound
                        };
                    }
                }
                else
                {
                    response.Error = new Error()
                    {
                        Details = "Section with id " + sectionID + " not found",
                        TargetSite = MethodBase.GetCurrentMethod().Name,
                        Type = ErrorTypes.ObjectNotFound
                    };
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response PublishIssue(string issueID)
        {

            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var issue = (from i in context.Issues where i.ID == issueID select i).SingleOrDefault();
                if(issue != null)
                {
                    lock(context)
                    {
                        issue.PublishDate = DateTime.Now;
                        issue.IsPublished = true;
                        context.SaveChanges();
                    }
                }
                else
                {
                    response.Error = new Error()
                    {
                        Details = "Issue with id " + issueID + " not found",
                        TargetSite = MethodBase.GetCurrentMethod().Name,
                        Type = ErrorTypes.ObjectNotFound
                    };
                }
                
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response GetSectionDetails(string sectionID)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var section = (from s in context.Sections where s.ID == sectionID select s).SingleOrDefault();

                if (section != null)
                {
                    var articles = (from a in context.Articles
                                    from SA in context.SectionArticles
                                    where SA.SectionID == sectionID && a.ID == SA.ArticleID
                                    select a).ToList();
                    section.Articles.AddRange(articles);

                    response.Result.Add(section);
                }
                else
                {
                    response.Error = new Error()
                    {
                        TargetSite = MethodBase.GetCurrentMethod().Name,
                        Type = ErrorTypes.ObjectNotFound,
                        Details = "Section with id " + sectionID + " no found"
                    };
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response GetIssueFiles(string issueID)
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var issue = (from i in context.Issues where i.ID == issueID select i).SingleOrDefault();
                if (issue != null)
                {
                    var sections = (from s in context.Sections
                                    from IS in context.IssueSections
                                    where IS.IssueID == issueID && s.ID == IS.SectionID
                                    select s).ToList();

                    foreach (var s in sections)
                    {
                        var articles = (from a in context.Articles
                                        from SA in context.SectionArticles
                                        where SA.SectionID == s.ID && a.ID == SA.ArticleID
                                        select a.AttachmentID).ToList();

                        var files = (from f in context.Attachments
                                     from a in articles
                                     where f.ID == a
                                     select f).ToList();
                        response.Result.AddRange(files);
                    }
                }
                else
                {
                    response.Error = new Error()
                    {
                        Type = ErrorTypes.ObjectNotFound,
                        Details = "Issue with id " + issueID +" not found.",
                        TargetSite = MethodBase.GetCurrentMethod().Name
                    };
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }

        public Response GetPublishedIssues()
        {
            Response response = new Response();
            response.ServiceID = ServiceID;
            try
            {
                var issues = (from i in context.Issues where i.IsPublished select i).ToList();
                if (issues.Count == 0)
                {
                    response.Error = new Error()
                    {
                        Type = ErrorTypes.ObjectNotFound,
                        Details = "Published issues not found.",
                        TargetSite = MethodBase.GetCurrentMethod().Name
                    };
                }
                else
                {
                    response.Result.AddRange(issues);
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex, "Exeption in " + this.GetType().Name + "." + MethodBase.GetCurrentMethod().Name + " method");
                response.Error = new Error()
                {
                    TargetSite = ex.TargetSite.Name,
                    Type = ErrorTypes.InternalError,
                    Details = ex.Message
                };
            }
            return response;
        }
    }
}
